package com.xyzm.mytest.nio;

import org.junit.Test;

import java.nio.ByteBuffer;

/**
 * 一、缓冲区（Buffer），在NIO中负责数据存取，缓冲区就是数组。
 * 根据类型(除去Boolean)不同，提供了相应类型的缓冲区
 * ByteBuffer
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 二、缓冲区存取
 * 通过allocate()获取缓冲区
 * put()
 * get()
 * 三、缓冲区的是个核心属性
 * capatiity：容量，表示缓冲区的大小，一旦声明不能修改
 * limit：界限，表示缓冲区可操作的数据大小
 * position：位置，表示缓冲区中正在操作数据的位置
 * mark:标记位置，可通过reset()恢复到mark的位置
 *
 * 0<=position<=limit<=capacity
 *
 * rewind()可重复读
 * 四、直接缓冲区与非直接缓冲区
 * 非直接缓冲区：通过allocate() 方法分配非直接缓冲区，将缓冲区建立在JVM内
 * 直接缓冲区：通过allocateDirect()方法分配直接缓冲区，将缓冲区建立在物理内存中，可以提升效率
 *             此方法返回的 缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区 。
 *  *          直接缓冲区的内容可以驻留在常规的垃圾回收堆之外.（有风险）
 *  *          将直接缓冲区主要分配给那些易受基础系统的本机 I/O 操作影响的大型、持久的缓冲区。
 *  *          最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们。
 *  *          直接字节缓冲区还可以过 通过FileChannel 的 map() 方法 将文件区域直接映射到内存中来创建 。该方法返回MappedByteBuffer
 */
public class TestBuffer {
    @Test
    public void test1(){
        String str = "abcde";
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        System.out.println("------------------allocate()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());

        byteBuffer.put(str.getBytes());
        System.out.println("------------------put()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());

        byteBuffer.flip();

        System.out.println("------------------flip()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());

        byte[] dst = new byte[byteBuffer.limit()];
        byteBuffer.get(dst);
        System.out.println(new String(dst));
        System.out.println("------------------get()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());

        //rewind：可重复读
        byteBuffer.rewind();
        System.out.println("------------------rewind()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());


        //clear：清空缓冲区,但是缓冲区中数据依然存在，数据处于“被遗忘状态”（位置等被清除）
        byteBuffer.clear();
        System.out.println("------------------clear()-----------------------");
        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());
        System.out.println((char)byteBuffer.get());

    }
    @Test
    public void test2(){
        String str = "abcd";
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.put(str.getBytes());

        System.out.println(byteBuffer.capacity());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.position());
        byteBuffer.flip();
        byte[] dst = new byte[byteBuffer.limit()];
        byteBuffer.get(dst,0,2);
        System.out.println(new String(dst));
        System.out.println(byteBuffer.position());
        //标记指针位置
        byteBuffer.mark();
        byteBuffer.get(dst,2,2);
        System.out.println(new String(dst,2,2));
        System.out.println(byteBuffer.position());
        //恢复到标记位置
        byteBuffer.reset();
        System.out.println(byteBuffer.position());

    }
}
